package internal

import (
	"database/sql"

	"gitee.com/hailib/mytree/errs"
	"go.uber.org/zap"
)

// 封装语句
type Stmt struct {
	*sql.Stmt        // sql 语句
	tx        Tx     // 事务
	query     string // 查询语句
	logger    Logger // 日志
}

// NewStmt 实例化新的语句
func NewStmt(stmt *sql.Stmt, query string, tx Tx, logger Logger) *Stmt {
	return &Stmt{
		logger: logger,
		query:  query,
		Stmt:   stmt,
		tx:     tx,
	}
}

// Exec 使用语句执行
//
// 1. 如果语句带有事务，则回滚事务
func (s *Stmt) Exec(args ...interface{}) (sql.Result, Error) {
	s.logger.Debug("stmt exec:", zap.String("tx", s.tx.Description()), zap.String("sql", s.query), zap.Any("args", args))
	result, err := s.Stmt.Exec(args...)
	if err != nil {
		if s.tx == nil {
			return nil, errs.New(errs.DbUpdateError, 210904165958, "exec error, error: %s, sql: %s, args: %v", err.Error(), s.query, args)
		} else {
			return nil, s.tx.Rollbackf(errs.DbUpdateError, 210904170009,
				"trans exec error, tx: %s, error: %s, args: %v",
				s.tx.Description(), err.Error(), s.query, args,
			)
		}
	}
	return result, nil
}

// Close 关闭语句
//
// 1. 如果语句有事务，则回滚事务
func (s *Stmt) Close() Error {
	err := s.Stmt.Close()
	if err != nil {
		if s.tx == nil {
			return errs.New(errs.DatabaseError, 210906113143, "close stmt error, query: %s, error: %s", s.query, err.Error())
		} else {
			return s.tx.Rollback(errs.New(
				errs.DatabaseError, 210906113353,
				"close stmt error, query: %s, tx: %s, error: %s",
				s.query, s.tx.Description(), err.Error(),
			))
		}
	}
	return nil
}
